/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.redis.constants.RedisKeyEnum;
import com.pig4cloud.pigx.common.customize.redis.utils.RedisUtils;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.system.dto.SystemPlatformAddDTO;
import com.pig4cloud.pigx.system.dto.SystemPlatformEditDTO;
import com.pig4cloud.pigx.system.entity.SystemPlatform;
import com.pig4cloud.pigx.system.entity.SystemProduct;
import com.pig4cloud.pigx.system.mapper.SystemPlatformMapper;
import com.pig4cloud.pigx.system.mapper.SystemProductMapper;
import com.pig4cloud.pigx.system.mapstruct.SystemPlatformStruct;
import com.pig4cloud.pigx.system.service.SystemPlatformService;
import com.pig4cloud.pigx.system.vo.SystemPlatformOptionVO;
import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 平台
 *
 * @since 2022-11-23 15:15:20
 */
@Service
@RequiredArgsConstructor
public class SystemPlatformServiceImpl extends ServiceImpl<SystemPlatformMapper, SystemPlatform> implements SystemPlatformService {

	private final SystemProductMapper systemProductMapper;

	private final SecurityUtil securityUtil;
	private final RedisUtils redisUtils;
	private final MysqlUtil mysqlUtil;

	/**
	 * 分页查询
	 *
	 * @param page      分页条件
	 * @param condition 查询条件
	 * @return {@link Page< SystemPlatform>}
	 * @since 2022/11/24 10:48
	 */
	@Override
	public Page<SystemPlatform> page(Page<SystemPlatform> page, SystemPlatform condition) {

		QueryWrapper<SystemPlatform> query = new QueryWrapper<>();
		query.lambda()
				.like(Strings.isNotBlank(condition.getName()), SystemPlatform::getName, condition.getName())
				.orderByDesc(SystemPlatform::getCreateTime);

		return baseMapper.selectPage(page, query);

	}

	/**
	 * 新增
	 *
	 * @param dto 数据
	 * @since 2022/11/24 11:31
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void add(SystemPlatformAddDTO dto) {

		SystemPlatform entity = SystemPlatformStruct.INSTANCE.addDTO2entity(dto);
		PigxUser user = SecurityUtil.getLoginUserNotNull();
		LocalDateTime now = LocalDateTime.now();

		entity.setCreateName(user.getName());
		entity.setUpdateName(user.getName());
		securityUtil.initCreateAbout(entity, user, now);

		if (baseMapper.add(entity) != 1) {
			String errorMsg = String.format("名称为{%s}的数据已存在", dto.getName());
			throw new DuckweedException(errorMsg);
		}

		// 刷新缓存
		redisUtils.flushPersistentCache(RedisKeyEnum.PLATFORM, entity.getId(), entity);

	}

	/**
	 * 修改
	 *
	 * @param dto 数据
	 * @since 2022/11/24 11:31
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void edit(SystemPlatformEditDTO dto) {

		SystemPlatform entity = SystemPlatformStruct.INSTANCE.editDTO2entity(dto);
		PigxUser user = SecurityUtil.getLoginUserNotNull();
		LocalDateTime now = LocalDateTime.now();

		entity.setUpdateName(user.getName());
		securityUtil.initUpdateAbout(entity, user, now);

		if (baseMapper.edit(entity) != 1) {
			String errorMsg = String.format("名称为{%s}的数据已存在", dto.getName());
			throw new DuckweedException(errorMsg);
		}

		// 刷新缓存
		entity = baseMapper.selectById(entity.getId());
		redisUtils.flushPersistentCache(RedisKeyEnum.PLATFORM, entity.getId(), entity);

	}

	/**
	 * 根据id逻辑删除
	 *
	 * @param id id
	 * @since 2022/11/24 11:31
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void del(Long id) {

		PigxUser user = SecurityUtil.getLoginUserNotNull();
		LocalDateTime now = LocalDateTime.now();

		// 检查引用
		checkReferences(id);

		UpdateWrapper<SystemPlatform> update = new UpdateWrapper<>();
		update.lambda()
				.set(SystemPlatform::getUpdateBy, user.getId())
				.set(SystemPlatform::getUpdateName, user.getName())
				.set(SystemPlatform::getUpdateTime, now)
				.set(SystemPlatform::getIsDeleted, null)
				.eq(SystemPlatform::getId, id);
		if (baseMapper.update(null, update) != 1) {
			throw new DuckweedException("操作失败");
		}

		// 刷新缓存
		redisUtils.delPersistentCache(RedisKeyEnum.PLATFORM, id);

	}

	/**
	 * 检查引用
	 *
	 * @param id id
	 * @since 2022/11/24 16:04
	 */
	private void checkReferences(Long id) {

		// 检查在产品表system_product中的引用
		QueryWrapper<SystemProduct> queryProduct = new QueryWrapper<>();
		queryProduct.lambda()
				.eq(SystemProduct::getPlatformId, id);
		Long productCount = systemProductMapper.selectCount(queryProduct);
		if (productCount > 0) {
			throw new DuckweedException("该平台数据正在被某个产品使用");
		}

	}

	/**
	 * 查询选项数据
	 *
	 * @return {@link List< SystemPlatformOptionVO>}
	 * @since 2022/11/24 14:26
	 */
	@Override
	public List<SystemPlatformOptionVO> option() {

		QueryWrapper<SystemPlatform> query = new QueryWrapper<>();
		query.lambda()
				.select(SystemPlatform::getId,
						SystemPlatform::getName)
				.orderByAsc(SystemPlatform::getName);
		List<SystemPlatform> list = baseMapper.selectList(query);

		return SystemPlatformStruct.INSTANCE.list2OptionVOList(list);

	}

	/**
	 * 初始化redis缓存
	 */
	@Override
	public void initRedis() {
		try {
			mysqlUtil.startLocalTx();
			List<SystemPlatform> list = new SystemPlatform().selectList(new QueryWrapper<SystemPlatform>() {{
				last("for update");
			}});
			for (SystemPlatform platform : list) {
				redisUtils.flushPersistentCache(RedisKeyEnum.PLATFORM,platform.getId(),platform);
			}
			mysqlUtil.commitLocalTx();
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
		}
	}
}
